<template lang="pug">
//- 一个瀑布流
view.a-waterfall-box
  view.waterfall-box.flex.wrap.start(v-show="pdata.columnWidth")
    view.ws(v-for="c,i in column" :class="`ws-${i}`")
      view.w(v-for="n in pdata.columnData[i]")
        slot(:item="n")
  aloading(:show="pdata.loading || !pdata.columnWidth")
  aempty(v-if="methods.isEmpty()" :text="emptyText" :icon="emtpyIcon" :size="emtpyIconSize")
</template>
<script setup>
import {getCurrentInstance, reactive, watch} from 'vue'

const emits = defineEmits(['update:modelValue'])
const props = defineProps({
  column: {type: Number, default: 2}, // 至少2列
  gap: {type: Number, default: 10}, // 列间隔,单位px
  modelValue: {type: Array, default: []},
  // 无数据
  emptyText: String,
  emtpyIcon: String,
  emtpyIconSize: {type: Number, default: 500},
})
const pdata = reactive({
  columnWidth: 0, // 单位px
  loading: false,
  columnData: [], // 实际渲染
})
const {ctx} = getCurrentInstance()
const query = uni.createSelectorQuery().in(ctx)

const methods = {
  columnWidth(){// 容器宽度
    return new Promise((resolve)=>{
      query.select('.a-waterfall-box').boundingClientRect(({width}) => {
        const {column, gap} = props
        if(width > 0) pdata.columnWidth = Number((width - (column - 1)*gap) / column).toFixed(2)
        resolve({width: pdata.columnWidth})
      }).exec()
    })
  },
  _initDefultColumnData(){
    pdata.columnData = Array(props.column).fill().map(n=>[])
  },
  columnData(items){
    const {column} = props
    if(pdata.columnData.length == 0) methods._initDefultColumnData()
    const col_len = Array(column).fill(0).map((n,i)=>pdata.columnData[i].length)
    items.forEach(n=>{
      const i = col_len.findIndex(n=>n == Math.min(...col_len))
      col_len[i]++
      pdata.columnData[i].push(n)
    })
  },
  isEmpty(){
    return !pdata.loading && (pdata.columnData.length == 0 || Array(props.column).fill(0).map((n,i)=>pdata.columnData[i].length).reduce((p,n)=>p+n) == 0)
  },
  async initColumnWidth(){
    function *sto(){
      setTimeout(methods.columnWidth, 300)
    }

    return new Promise((resolve, reject)=>{
      if(pdata.columnWidth / 1 > 0){
        resolve()
      }else{
        const _sto = sto()
        const siv = setInterval(()=>{
          if(pdata.columnWidth / 1 > 0){
            clearInterval(siv)
            resolve()
          }else{
            _sto.next()
          }
        }, 300)
      }
    })
  }
}

watch(()=>props.modelValue, list=>{
  if(!list.length) methods._initDefultColumnData()

  methods.initColumnWidth().then(()=>pdata.loading = false)

})

defineExpose({
  loadMore: (promise)=>{
    pdata.loading = true
    promise().then(items=>{
      methods.columnData(items)
      emits('update:modelValue', props.modelValue.concat(items))
    })
  }
})

</script>
<style lang="scss" scoped>
@import '/common/scss/mixin.scss';
.a-waterfall-box{
  .waterfall-box{
    column-gap: calc(v-bind('props.gap') * 1px);
    .w{
      width: calc(v-bind('pdata.columnWidth') * 1px);
      margin-bottom: calc(v-bind('props.gap') * 1px);
    }
  }
}
</style>